﻿namespace ImapComponent.Net.Mail.Utils
{
    using System;
    using System.Collections.Specialized;
    using System.IO;
    using System.Net.Mime;

    using ImapComponent.Net.Mail.Imap4;

    /// <summary>
    /// Represents the Imap helper.
    /// </summary>
    internal class Helper
    {
        #region Methods

        /// <summary>
        /// Gets the system flags.
        /// </summary>
        /// <param name="flags">All flags.</param>
        /// <returns>System flags.</returns>
        internal static SystemMessageFlags GetSystemFlags(string[] flags)
        {
            SystemMessageFlags systemFlags = SystemMessageFlags.None;

            foreach (string systemFlag in Enum.GetNames(typeof(SystemMessageFlags)))
            {
                if (flags.Contains("\\" + systemFlag))
                {
                    systemFlags |= (SystemMessageFlags)Enum.Parse(typeof(SystemMessageFlags), systemFlag);
                }
            }

            if (flags.Contains("\\*"))
            {
                systemFlags |= SystemMessageFlags.CanCreate;
            }

            return systemFlags;
        }

        /// <summary>
        /// Gets the mail adddress string.
        /// </summary>
        /// <param name="data">A data.</param>
        /// <returns>The mail address string.</returns>
        internal static string GetMailAddressString(string data)
        {
            try
            {
                string firstPart;
                string secondPart = "NIL";
                string thirdPart;
                string fourthPart;

                int position = data.IndexOf("(");

                string substring = data.Substring(position + 1);

                if (substring.StartsWith("NIL"))
                {
                    firstPart = "NIL";
                }
                else
                {
                    firstPart = "\"" + substring.GetQuotedString() + "\"";
                }

                substring = substring.Substring(firstPart.Length + 1);

                if (!substring.StartsWith("NIL"))
                {
                    throw new InvalidDataException("Invalid email address.");
                }
                else
                {
                    substring = substring.Substring(secondPart.Length + 1);
                }

                if (substring.StartsWith("NIL"))
                {
                    thirdPart = "NIL";
                }
                else
                {
                    thirdPart = "\"" + substring.GetQuotedString() + "\"";
                }

                substring = substring.Substring(thirdPart.Length + 1);

                if (substring.StartsWith("NIL"))
                {
                    fourthPart = "NIL";
                }
                else
                {
                    fourthPart = "\"" + substring.GetQuotedString() + "\"";
                }

                substring = substring.Substring(fourthPart.Length);

                if (!substring.StartsWith(")"))
                {
                    throw new InvalidDataException("Invalid email address.");
                }
                else 
                {
                    return firstPart + " " + secondPart + " " + thirdPart + " " + fourthPart;
                }
            }
            catch
            {
                /// invalid email address
                return "NIL NIL NIL NIL";
            }
        }

        /// <summary>
        /// Gets the content type from the string.
        /// </summary>
        /// <param name="contentData">The content data.</param>
        /// <returns>A content type.</returns>
        internal static ContentType GetContentType(string contentData)
        {
            string[] parameters = contentData.Trim(new char[] { ' ', ';' }).Split(new char[] { ';' });

            string modifiedString = parameters[0].Trim() + ";";
            string type = modifiedString;
            NameValueCollection nameValueParameters = new NameValueCollection();

            if (parameters.Length > 1)
            {
                for (int i = 1; i < parameters.Length; i++)
                {
                    if (parameters[i].IndexOf('=') > -1)
                    {
                        string[] nameValue = parameters[i].Trim().Split(new char[] { '=' }, 2);
                        nameValueParameters.Add(nameValue[0].Trim().ToLower(), nameValue[1].Trim());
                    }
                    else
                    {
                        throw new InvalidDataException("Invalid parameter.");
                    }
                }

                foreach (string key in nameValueParameters.AllKeys)
                {
                    modifiedString += key + "=" + nameValueParameters.GetValues(key)[0] + ";";
                }
            }

            ContentType contentType;

            try
            {
                contentType = new ContentType(modifiedString);
            }
            catch
            {
                contentType = new ContentType(type);

                if (nameValueParameters.AllKeys.Contains("boundary"))
                {
                    contentType.Boundary = nameValueParameters.GetValues("boundary")[0];
                }

                if (nameValueParameters.AllKeys.Contains("name"))
                {
                    contentType.Name = nameValueParameters.GetValues("name")[0];
                }

                if (nameValueParameters.AllKeys.Contains("charset"))
                {
                    contentType.CharSet = nameValueParameters.GetValues("charset")[0];
                }
            }

            return contentType;
        }

        /// <summary>
        /// Gets the content disposition from the string.
        /// </summary>
        /// <param name="contentData">The content data.</param>
        /// <returns>The content disposition.</returns>
        internal static ContentDisposition GetContentDisposition(string contentData)
        {
            string[] parameters = contentData.Trim(new char[] { ' ', ';' }).Split(new char[] { ';' });

            string modifiedString = parameters[0].Trim() + ";";
            string disposition = modifiedString;
            NameValueCollection nameValueParameters = new NameValueCollection();

            if (parameters.Length > 1)
            {
                for (int i = 1; i < parameters.Length; i++)
                {
                    if (parameters[i].IndexOf('=') > -1)
                    {
                        string[] nameValue = parameters[i].Trim().Split(new char[] { '=' }, 2);
                        nameValueParameters.Add(nameValue[0].Trim().ToLower(), nameValue[1].Trim());
                    }
                    else
                    {
                        throw new InvalidDataException("Invalid parameter.");
                    }
                }

                foreach (string key in nameValueParameters.AllKeys)
                {
                    modifiedString += key + "=" + nameValueParameters.GetValues(key)[0] + ";";
                }
            }

            ContentDisposition contentDisposition;

            try
            {
                contentDisposition = new ContentDisposition(modifiedString);
            }
            catch
            {
                contentDisposition = new ContentDisposition(disposition);

                if (nameValueParameters.AllKeys.Contains("filename"))
                {
                    contentDisposition.FileName = nameValueParameters.GetValues("filename")[0];
                }
            }

            return contentDisposition;
        }

        #endregion // Methods
    }
}
